package com.fub.view.mapcomponents;

import java.util.List;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;

import com.fub.guidance.Edge;
import com.fub.guidance.Graph;
import com.fub.guidance.Point;
import com.fub.guidance.Vertex;
import com.fub.util.Util;
import com.fub.util.PreferenceDAO;

public class GraphComponent {

	private static final int SPACING = 5;
	private static final int CORIDOR_POINT_SIZE = 3;
	private Graph graph;
	private Path edgePath;
	private Paint paintEdge;
	private Paint paintWeight;
	private Paint paintPoint;
	private Canvas canvas;
	private PreferenceDAO preferenceDao;

	public GraphComponent(PreferenceDAO preferenceDao) {
		this.graph = Graph.getInstance();
		this.preferenceDao = preferenceDao;
		this.edgePath = new Path();
		initPaints();
	}

	private void initPaints() {
		// edges
		this.paintEdge = new Paint(Paint.ANTI_ALIAS_FLAG);
		this.paintEdge.setStyle(Paint.Style.STROKE);
		this.paintEdge.setStrokeWidth(1);
		this.paintEdge.setColor(Color.argb(50, 0, 0, 255));
		// weight of the edges
		this.paintWeight = new Paint();
		this.paintWeight.setAntiAlias(true);
		this.paintWeight.setTextSize(10);
		this.paintWeight.setColor(Color.BLACK);
		// vertices
		this.paintPoint = new Paint();
		this.paintPoint.setAntiAlias(true);
		this.paintPoint.setStyle(Paint.Style.FILL);
		this.paintPoint.setColor(Color.GRAY);
	}

	public void draw(Canvas canvas) {
		this.canvas = canvas;
		drawCoridorNodes();
		drawEdges();
	}

	private void drawEdges() {
		List<Edge> edges = this.graph.getEdges();
		for (Edge edge : edges) {
			addEdgeToEdgePath(edge);
		}
		this.canvas.drawPath(this.edgePath, this.paintEdge);
	}

	private void addEdgeToEdgePath(Edge edge) {
		Vertex from = this.graph.getNodeById(edge.getSourceId());
		if (from.getPosition().getZ() == this.preferenceDao.getCurrentEtage()) {
			Vertex to = this.graph.getNodeById(edge.getDestinationId());
			paintPath(from, to, edge);
		}
	}

	private void drawCoridorNodes() {
		for (Vertex node : this.graph.getNodes()) {
			if (node.getPosition().getZ() == this.preferenceDao.getCurrentEtage()
					&& Util.isCoridorType(node)) {
				Point positionOnDisplay = Util.calculateZoomedPosition(
						node.getPosition(), this.preferenceDao);
				this.canvas.drawCircle(positionOnDisplay.getX(),
						positionOnDisplay.getY(), CORIDOR_POINT_SIZE,
						this.paintPoint);
			}
		}
	}

	private void paintPath(Vertex from, Vertex to, Edge edge) {
		Point nodePositionOnDisplay = Util.calculateZoomedPosition(
				from.getPosition(), this.preferenceDao);
		Point neighbourPositionOnDisplay = Util.calculateZoomedPosition(
				to.getPosition(), this.preferenceDao);
		this.edgePath.moveTo(nodePositionOnDisplay.getX(),
				nodePositionOnDisplay.getY());
		this.edgePath.lineTo(neighbourPositionOnDisplay.getX(),
				neighbourPositionOnDisplay.getY());
		paintWeight(from, to, edge);
	}

	private void paintWeight(Vertex node, Vertex neighbour, Edge edge) {
		int diffX = (neighbour.getPosition().getX() - node.getPosition().getX()) / 2;
		int diffY = (neighbour.getPosition().getY() - node.getPosition().getY()) / 2;
		int weightTextPosX = (node.getPosition().getX() + diffX / 2);
		int weightTextPosY = (node.getPosition().getY() + diffY / 2);
		Point textPos = new Point(weightTextPosX, weightTextPosY,
				this.preferenceDao.getCurrentEtage());
		Point textPosOnDisplay = Util.calculateZoomedPosition(textPos,
				this.preferenceDao);
		this.canvas.drawText(edge.getWeight() + "", textPosOnDisplay.getX()
				+ SPACING, textPosOnDisplay.getY() + SPACING, this.paintWeight);
	}
}
